package ig.finanzas;

import ig.util.excepciones.DatoInvalidoExcepcion;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

/**
 * Modela una coleccion de bandas y los metodos que se pueden operar sobre ellas.
 * @author lfgarcia
 */
public class ManejadorBandas extends ManejadorRangosTiempo {

    public ManejadorBandas(List bandas) throws DatoInvalidoExcepcion {
        super(bandas);
    }

    public List<Banda> getColeccionBandas() {
        return rangos;
    }

    public void setBanda(int index,Banda banda){
        this.rangos.set(index, banda);
    }
    /**
     * Crea un manejador de bandas (rangos de tiempo) a partir de una fecha y una configuracion
     * de los periodos. La definicion de los periodos es del tipo: 30, 60, 145, 180,. etc.
     * @param fecha
     * @param confPeriodos
     * @return
     * @throws DatoInvalidoExcepcion Si alguno de los datos de la configuracion de los periodos
     * de una banda es 0, o si un dato es menor a su inmediatamente anterior.
     */
    public static synchronized ManejadorBandas crearBandas(Date fecha, int[] confPeriodos) throws DatoInvalidoExcepcion {
        List bandas = new ArrayList();
        Date fecha1;
        boolean isNegativa = false;
        if (confPeriodos.length > 0 && confPeriodos[0] < 0) {
            isNegativa = true;
            fecha.setTime(fecha.getTime() + ((1000 * 60 * 60 * 24) * confPeriodos[0]));
            int[] confPeriodosA = new int[confPeriodos.length - 1];
            for (int i = 1; i < confPeriodos.length; i++) {                
                confPeriodosA[i - 1] = confPeriodos[i ] + Math.abs(confPeriodos[0]);
                //System.out.println(confPeriodosA[i - 1]);
            }
            confPeriodos = confPeriodosA;
        }
        //System.out.println("fecha:" + fecha);
        
        Date fecha2 = (Date) fecha.clone();

        if (confPeriodos != null && confPeriodos.length > 0 && confPeriodos[0] != 0) {
            GregorianCalendar gcFecha = new GregorianCalendar();
            gcFecha.setTime(fecha);
            boolean finDeMes = gcFecha.getActualMaximum(Calendar.DATE) == gcFecha.get(Calendar.DATE);
            int mesFechaAnalizada = gcFecha.get(Calendar.MONTH);
            int diaFechaAnalizada = gcFecha.get(Calendar.DATE);
            int valorAnterior = 0;
            for (int i = 0; i < confPeriodos.length; i++) {
                if (confPeriodos[i] == valorAnterior && !isNegativa) {
                    throw new DatoInvalidoExcepcion("Un periodo de configuracion de una banda no puede ser igual al periodo anterior.");
                }
                fecha1 = (Date) fecha2.clone();
                if (confPeriodos[i] % 30 == 0) {
                    if ((finDeMes) || (((mesFechaAnalizada + (int) (confPeriodos[i] / 30)) % 12 == 2 - 1) && (diaFechaAnalizada >= 29))) {
                        gcFecha.setTime(fecha);
                        gcFecha.set(Calendar.DATE, 1);
                        gcFecha.add(Calendar.MONTH, (int) (confPeriodos[i] / 30));
                        gcFecha.set(Calendar.DATE, gcFecha.getActualMaximum(Calendar.DATE));
                        fecha2 = gcFecha.getTime();
                    } else {
                        gcFecha.setTime(fecha);
                        gcFecha.add(Calendar.MONTH, (int) (confPeriodos[i] / 30));
                        fecha2 = gcFecha.getTime();
                    }
                } else {
                    gcFecha.setTime(fecha);
                    gcFecha.add(Calendar.DATE, confPeriodos[i]);
                    fecha2 = gcFecha.getTime();
                }                
                bandas.add(new Banda(fecha1, fecha2));
                valorAnterior = confPeriodos[i];
            }
        }
        if (confPeriodos.length > 0 && confPeriodos[0] != 0) {
            bandas.add(new Banda(fecha2));
        } else if (confPeriodos.length > 0) {
            bandas.add(new Banda(fecha, new Date(java.sql.Timestamp.valueOf("9999-12-31 00:00:00").getTime())));
        }
        ManejadorBandas m = new ManejadorBandas(bandas);
        return m;
    }

    public static void main(String[] arg) throws DatoInvalidoExcepcion {
        ManejadorBandas bandas = ManejadorBandas.crearBandas(
                new Date(
                java.sql.Timestamp.valueOf("2009-05-31 00:00:00.0").getTime()), new int[]{180,545,910,1275,1640,2190,2920,3650}
        );
//        System.out.println(bandas.getColeccionBandas());
        Iterator i = bandas.getColeccionBandas().iterator();
        int count=1;
        while (i.hasNext()) {
            Banda banda = (Banda) i.next();
            banda.setIdInterna(count++);
            System.out.println(banda.getIdInterna()+":"+new Timestamp( banda.getFechaInicio().getTime()) + " - " + (banda.getFechaFin()!=null ? new Timestamp(banda.getFechaFin().getTime() ) : null ));
        }
        System.out.println(3 == 3 + 1);
    }

    @Override
    public String toString() {
        return super.toString();
    }

}

